`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/07/27 11:54:01
// Design Name: 
// Module Name: mips_core
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module mips_core(
    input wire clk, rst,
    input wire [5:0] ext_int,
    output wire flushF,

    //instr
    output wire         inst_req,
    output wire         inst_wr,
    output wire [1:0]   inst_size,
    output wire [31:0]  inst_addr,
    output wire [31:0]  inst_wdata,
    input wire          inst_addr_ok,
    input wire          inst_data_ok,
    input wire [31:0]   inst_rdata,

    //data
    output wire         data_req,
    output wire         data_wr,
    output wire [1:0]   data_size,
    output wire [31:0]  data_addr,
    output wire [31:0]  data_wdata,
    input wire          data_addr_ok,
    input wire          data_data_ok,
    input wire [31:0]   data_rdata,

    //debug
    output wire [31:0]  debug_wb_pc,      
    output wire [3:0]   debug_wb_rf_wen,
    output wire [4:0]   debug_wb_rf_wnum, 
    output wire [31:0]  debug_wb_rf_wdata,

    output wire [1:0] data_sram_size
    );

    wire        inst_sram_en    ;
    wire [31:0] inst_sram_addr  ;
    wire [31:0] inst_sram_rdata ;

    wire        data_sram_en    ;
    wire [31:0] data_sram_addr  ;
    wire [31:0] data_sram_rdata ;
    wire [3:0]  data_sram_wen   ;
    wire [31:0] data_sram_wdata ;

    wire stallreq_from_if,stallreq_from_mem;
    wire stallreq;

    // instruction memory
    wire [31:0]  pcF;
    wire [31:0]  instrF;
    
    // data memory
    wire         memenM;
    wire [3:0]   selM;
    wire [31:0]  aluoutM,writedataM;
    wire [31:0]  readdataM;
    
    // debug
	wire [31:0]  pcW;
	wire [4:0]   writeregW;
	wire [31:0]  resultW;

    // D
    wire [5:0]  opD;
    wire [4:0]  rtD;
    wire [4:0]  rsD;
    wire [5:0]  functD;
    wire        equalD;
    wire        branchD;
	wire        pcsrcD;
    wire        jumpD;
    wire        jalD;
    wire        jrD;
    wire        balD;
    wire        invalidD;
    wire        pcInvalidD;
    wire        stallD;
    wire        is_soft_intD;

    // E
    wire        stallE;
    wire        flushE;
    wire        memtoregE;
    wire        cp0toregE;
    wire        alusrcE;
    wire        regdstE;
    wire        regwriteE;
    wire        jalE;
    wire        balE;
    wire[7:0]   alucontrolE;
    wire        hilo_writeE;
    wire        pcInvalidE;

	// M
	wire        stallM;
	wire        flushM;
    wire        memtoregM;
    wire        memwriteM;
    wire        regwriteM;
    // wire        memenM;
    wire[7:0]   alucontrolM;
    wire        cp0weM;
    wire        cp0toregM;

    // W
    wire        stallW;
    wire        flushW;
    wire        memtoregW;
    wire        regwriteW;

    wire [1:0]  axi_size;

    // ==================== controller module & datapath ====================>>
	// ======================================================================>>
	controller c(
		.clk              (clk     ), 
		.rst              (rst    ),
		//decode stage
		.instr_opD        (opD        ),
		.instr_rtD        (rtD        ),
		.instr_rsD        (rsD        ),
		.instr_funD       (functD     ),
		.equalD           (equalD     ),
		.branchD          (branchD    ),
		.pcsrcD           (pcsrcD     ),
		.jumpD            (jumpD      ),
		.jalD             (jalD       ), 
		.jrD              (jrD        ), 
		.balD             (balD       ),
		.invalidD         (invalidD   ),
		.stallD           (stallD     ),
		
		//execute stage
		.stallE           (stallE     ),
		.flushE           (flushE     ),
		.memtoregE        (memtoregE  ),
		.cp0toregE        (cp0toregE  ),
		.alusrcE          (alusrcE    ),
		.regdstE          (regdstE    ),
		.regwriteE        (regwriteE  ),
		.jalE             (jalE       ),
		.balE             (balE       ),
		.alucontrolE      (alucontrolE),
		.hilo_write_enaE  (hilo_writeE),

		//mem stage
		.stallM           (stallM     ),
		.flushM           (flushM     ),
		.memtoregM        (memtoregM  ),
		.memwriteM        (memwriteM  ),
		.regwriteM        (regwriteM  ),
		.memenM           (memenM     ),
		.alucontrolM      (alucontrolM),
		.cp0weM           (cp0weM     ),
		.cp0toregM        (cp0toregM  ),
		//write back stage
		.stallW           (stallW     ),
		.flushW           (flushW     ),
		.memtoregW        (memtoregW  ),
		.regwriteW        (regwriteW  ),
		.stallreq         (stallreq   )
		);


	datapath dp(
		.clk              (clk        ), 
		.rst              (rst    ),
		//fetch stage
		.pcF              (pcF        ),
		.instrF           (instrF     ),
        .flushF           (flushF     ),
		//decode stage
		.pcsrcD           (pcsrcD     ),
		.branchD          (branchD    ),
		.jumpD            (jumpD      ),
		.jalD             (jalD       ),
		.jrD              (jrD        ),
		.balD             (balD       ),
		.equalD           (equalD     ),
		.opD              (opD        ),
		.functD           (functD     ),
		.rtD              (rtD        ),
		.rsD              (rsD        ),
		.invalidD         (invalidD   ),
		.stallD           (stallD     ),
        .pcInvalidD       (pcInvalidD),
        .is_soft_intD  (is_soft_intD),
		//execute stage
		.memtoregE        (memtoregE  ),
		.cp0toregE        (cp0toregE  ),
		.alusrcE          (alusrcE    ),
		.regdstE          (regdstE    ),
		.regwriteE        (regwriteE  ),
		.alucontrolE      (alucontrolE),
		.hilo_writeE      (hilo_writeE),
		.jalE             (jalE       ),
		.balE             (balE       ),
		.stallE           (stallE     ),
		.flushE           (flushE     ),
        .pcInvalidE       (pcInvalidE),
		//mem stage
		.memtoregM        (memtoregM  ),
		.regwriteM        (regwriteM  ),
		.aluoutM          (aluoutM    ),
		.writedataM2      (writedataM ),
		.selM2            (selM       ),
		.readdataM        (readdataM  ),
		.alucontrolM      (alucontrolM),
		.stallM           (stallM     ),
		.flushM           (flushM     ),
		.cp0weM           (cp0weM     ),
		.cp0toregM        (cp0toregM  ),
        .excepttypeM      (excepttypeM),
		//writeback stage
		.memtoregW        (memtoregW  ),
		.regwriteW        (regwriteW  ),
		.writeregW        (writeregW  ),
		.stallW           (stallW     ),
		.flushW           (flushW     ),
		.pcW              (pcW        ),
		.resultW          (resultW    ),
		//exception
		.int              (ext_int        ),
        .inst_stall       (stallreq_from_if ),
        .data_stall       (stallreq_from_mem),
		.stallreq         (stallreq   ),

        .axi_size         (axi_size   )
	    );
	// ======================================================================<<
	// ==================== controller module & datapath ====================<<

    // 接口信号
    // inst memory
    assign inst_sram_en    = 1'b1;
    assign inst_sram_wen   = 4'b0000;
    assign inst_sram_addr  = pcF;
    assign inst_sram_wdata = 32'h0000_0000;
    assign instrF          = inst_sram_rdata;
    
    // data memory
    assign data_sram_en    = memenM & ~(|excepttypeM);
    assign data_sram_write = data_sram_wen[0] || data_sram_wen[1] || data_sram_wen[2] || data_sram_wen[3];
    assign data_sram_size  = axi_size;

    assign data_sram_wen   = selM;
    // assign data_sram_addr  = (aluoutM[31:16] == 16'hbfaf)?{16'h1faf,aluoutM[15:0]}:aluoutM;
    assign data_sram_addr  = aluoutM;
    assign data_sram_wdata = writedataM;
    assign readdataM       = data_sram_rdata;


    // debug
    assign debug_wb_pc          = pcW;      
    assign debug_wb_rf_wen      = {4{regwriteW}};
    assign debug_wb_rf_wnum     = writeregW; 
    assign debug_wb_rf_wdata    = resultW;


	// ======================================================================<<
	// ========================== sram to sram-like =========================<<
    assign i_sram_like_rst= rst || flushF;
    i_sram_to_sram_like i_sram_to_sram_like(
        .clk(clk), .rst(i_sram_like_rst),
        .pcInvalidE       (pcInvalidE),
        .pcInvalidD       (pcInvalidD),
        .is_soft_intD     (is_soft_intD),
        //sram
        .inst_sram_en(inst_sram_en),
        .inst_sram_addr(inst_sram_addr),
        .inst_sram_rdata(inst_sram_rdata),
        .i_stall(stallreq_from_if), // i_stall - stallreq_from_if
        //sram like
        .inst_req(inst_req), 
        .inst_wr(inst_wr),
        .inst_size(inst_size),
        .inst_addr(inst_addr),   
        .inst_wdata(inst_wdata),
        .inst_addr_ok(inst_addr_ok),
        .inst_data_ok(inst_data_ok),
        .inst_rdata(inst_rdata),

        .longest_stall(stallreq)
    );

    d_sram_to_sram_like d_sram_to_sram_like(
        .clk(clk), .rst(rst),
        //sram
        .data_sram_en(data_sram_en),
        .data_sram_addr(data_sram_addr),
        .data_sram_rdata(data_sram_rdata),
        .data_sram_wen(data_sram_wen),
        .data_sram_wdata(data_sram_wdata),
        .d_stall(stallreq_from_mem), // d_stall - stallreq_from_mem
        //sram like
        .data_req(data_req),    
        .data_wr(data_wr),
        .data_size(data_size),
        .data_addr(data_addr),   
        .data_wdata(data_wdata),
        .data_addr_ok(data_addr_ok),
        .data_data_ok(data_data_ok),
        .data_rdata(data_rdata),

        .longest_stall(stallreq),

        .axi_size(axi_size)
    );

endmodule
